package com.xc.quickstart.common.util;

import com.xc.quickstart.common.context.CommonContext;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Pattern;

public class DateUtil {
    private static final Logger logger = LoggerFactory.getLogger(DateUtil.class);
    public static final long ONE_DAY_SECONDS = 86400L;
    public static final long ONE_DAY_MILL_SECONDS = 86400000L;
    public static final String shortFormat = "yyyyMMdd";
    public static final String longFormat = "yyyyMMddHHmmss";
    public static final String webFormat = "yyyy-MM-dd";
    public static final String timeFormat = "HHmmss";
    public static final String monthFormat = "yyyyMM";
    public static final String chineseDtFormat = "yyyy年MM月dd日";
    public static final String newFormat = "yyyy-MM-dd HH:mm:ss";
    public static final String noSecondFormat = "yyyy-MM-dd HH:mm";

    private DateUtil() {
    }

    public static DateFormat getNewDateFormat(String pattern) {
        DateFormat df = new SimpleDateFormat(pattern);
        df.setLenient(false);
        return df;
    }

    public static String format(Date date, String format) {
        return date == null ? null : (new SimpleDateFormat(format)).format(date);
    }

    public static Date parseDateNoTime(String sDate) throws ParseException {
        DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        if (sDate != null && sDate.length() >= "yyyyMMdd".length()) {
            if (!StringUtils.isNumeric(sDate)) {
                throw new ParseException("not all digit", 0);
            } else {
                return dateFormat.parse(sDate);
            }
        } else {
            throw new ParseException("length too little", 0);
        }
    }

    public static Date parseDateToTime(String sDate)  {
        if (sDate == null) {
            return null;
        }
        DateFormat dateFormat = new SimpleDateFormat(webFormat);
        try {
            return dateFormat.parse(sDate);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static Date parseDateNoTime(String sDate, String format) {
        try {
            if (StringUtils.isBlank(format)) {
                return null;
            } else {
                DateFormat dateFormat = new SimpleDateFormat(format);
                if (sDate != null && sDate.length() >= format.length()) {
                    return dateFormat.parse(sDate);
                }
                return null;
            }
        }catch (Exception e) {
            return null;
        }
    }

    public static Date parseDateNoTimeWithDelimit(String sDate, String delimit) throws ParseException {
        sDate = sDate.replaceAll(delimit, "");
        DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        if (sDate != null && sDate.length() == "yyyyMMdd".length()) {
            return dateFormat.parse(sDate);
        } else {
            throw new ParseException("length not match", 0);
        }
    }

    public static Date parseDateLongFormat(String sDate) {
        DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        Date d = null;
        if (sDate != null && sDate.length() == "yyyyMMddHHmmss".length()) {
            try {
                d = dateFormat.parse(sDate);
            } catch (ParseException var4) {
                return null;
            }
        }

        return d;
    }

    public static Date parseDateNewFormat(String sDate) {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d = null;
        dateFormat.setLenient(false);
        if (sDate != null && sDate.length() == "yyyy-MM-dd HH:mm:ss".length()) {
            try {
                d = dateFormat.parse(sDate);
            } catch (ParseException var4) {
                return null;
            }
        }

        return d;
    }

    public static Date parseDateFormat(String sDate) {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date d = null;
        dateFormat.setLenient(false);
        if (sDate != null && sDate.length() == "yyyy-MM-dd".length()) {
            try {
                d = dateFormat.parse(sDate);
            } catch (ParseException var4) {
                return null;
            }
        }

        return d;
    }

    public static int getDayOfMonth(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    public static String getFirstDayOfMonth(int count) {
        SimpleDateFormat myFormatter = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.add(Calendar.MONTH,count);
        return myFormatter.format(cal.getTime());
    }

    public static String getFirstDayOfMonth(Date date) {
        SimpleDateFormat myFormatter = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int last = cal.getActualMinimum(Calendar.DAY_OF_MONTH);
        cal.set(Calendar.DAY_OF_MONTH, last);
        return myFormatter.format(cal.getTime());
    }


    public static String getMonthLastDay(Date date) {
        SimpleDateFormat myFormatter = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int last = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
        cal.set(Calendar.DAY_OF_MONTH, last+1);
        return myFormatter.format(cal.getTime());
    }


    public static Date addHours(Date date, long hours) {
        return addMinutes(date, hours * 60L);
    }

    public static Date addMinutes(Date date, long minutes) {
        return addSeconds(date, minutes * 60L);
    }

    public static Date addSeconds(Date date1, long secs) {
        return new Date(date1.getTime() + secs * 1000L);
    }

    public static boolean isValidHour(String hourStr) {
        if (!StringUtils.isEmpty(hourStr) && StringUtils.isNumeric(hourStr)) {
            int hour = new Integer(hourStr);
            if (hour >= 0 && hour <= 23) {
                return true;
            }
        }

        return false;
    }

    public static boolean isValidMinuteOrSecond(String str) {
        if (!StringUtils.isEmpty(str) && StringUtils.isNumeric(str)) {
            int hour = new Integer(str);
            if (hour >= 0 && hour <= 59) {
                return true;
            }
        }

        return false;
    }

    public static Date addDays(Date date1, long days) {
        return addSeconds(date1, days * 86400L);
    }

    public static String getTomorrowDateString(String sDate) throws ParseException {
        Date aDate = parseDateNoTime(sDate);
        aDate = addSeconds(aDate, 86400L);
        return getDateString(aDate);
    }

    public static String getLongDateString(Date date) {
        DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        return getDateString(date, dateFormat);
    }

    public static String getNewFormatDateString(Date date) {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return getDateString(date, dateFormat);
    }

    public static String getDateString(Date date, DateFormat dateFormat) {
        return date != null && dateFormat != null ? dateFormat.format(date) : null;
    }

    public static String getYesterDayDateString(String sDate) throws ParseException {
        Date aDate = parseDateNoTime(sDate);
        aDate = addSeconds(aDate, -86400L);
        return getDateString(aDate);
    }

    public static String getDateString(Date date) {
        DateFormat df = getNewDateFormat("yyyyMMdd");
        return df.format(date);
    }

    public static String getWebDateString(Date date) {
        DateFormat dateFormat = getNewDateFormat("yyyy-MM-dd");
        return getDateString(date, dateFormat);
    }

    public static String getChineseDateString(Date date) {
        DateFormat dateFormat = getNewDateFormat("yyyy年MM月dd日");
        return getDateString(date, dateFormat);
    }

    public static String getTodayString() {
        DateFormat dateFormat = getNewDateFormat("yyyyMMdd");
        return getDateString(new Date(), dateFormat);
    }

    public static String getTimeString(Date date) {
        DateFormat dateFormat = getNewDateFormat("HHmmss");
        return getDateString(date, dateFormat);
    }

    public static String getBeforeDayString(int days) {
        Date date = new Date(System.currentTimeMillis() - 86400000L * (long)days);
        DateFormat dateFormat = getNewDateFormat("yyyyMMdd");
        return getDateString(date, dateFormat);
    }

    public static long getDiffSeconds(Date one, Date two) {
        Calendar sysDate = new GregorianCalendar();
        sysDate.setTime(one);
        Calendar failDate = new GregorianCalendar();
        failDate.setTime(two);
        return (sysDate.getTimeInMillis() - failDate.getTimeInMillis()) / 1000L;
    }

    public static long getDiffMinutes(Date one, Date two) {
        Calendar sysDate = new GregorianCalendar();
        sysDate.setTime(one);
        Calendar failDate = new GregorianCalendar();
        failDate.setTime(two);
        return (sysDate.getTimeInMillis() - failDate.getTimeInMillis()) / 60000L;
    }

    public static long getDiffDays(Date one, Date two) {
        Calendar sysDate = new GregorianCalendar();
        sysDate.setTime(one);
        Calendar failDate = new GregorianCalendar();
        failDate.setTime(two);
        return (sysDate.getTimeInMillis() - failDate.getTimeInMillis()) / 86400000L;
    }

    public static String getBeforeDayString(String dateString, int days) {
        DateFormat df = getNewDateFormat("yyyyMMdd");

        Date date;
        try {
            date = df.parse(dateString);
        } catch (ParseException var5) {
            date = new Date();
        }

        date = new Date(date.getTime() - 86400000L * (long)days);
        return df.format(date);
    }

    public static boolean isValidShortDateFormat(String strDate) {
        if (strDate.length() != "yyyyMMdd".length()) {
            return false;
        } else {
            try {
                Integer.parseInt(strDate);
            } catch (Exception var4) {
                return false;
            }

            DateFormat df = getNewDateFormat("yyyyMMdd");

            try {
                df.parse(strDate);
                return true;
            } catch (ParseException var3) {
                return false;
            }
        }
    }

    public static boolean isValidShortDateFormat(String strDate, String delimiter) {
        String temp = strDate.replaceAll(delimiter, "");
        return isValidShortDateFormat(temp);
    }

    public static boolean isValidLongDateFormat(String strDate) {
        if (strDate.length() != "yyyyMMddHHmmss".length()) {
            return false;
        } else {
            try {
                Long.parseLong(strDate);
            } catch (Exception var4) {
                return false;
            }

            DateFormat df = getNewDateFormat("yyyyMMddHHmmss");

            try {
                df.parse(strDate);
                return true;
            } catch (ParseException var3) {
                return false;
            }
        }
    }

    public static boolean isValidLongDateFormat(String strDate, String delimiter) {
        String temp = strDate.replaceAll(delimiter, "");
        return isValidLongDateFormat(temp);
    }

    public static String getShortDateString(String strDate) {
        return getShortDateString(strDate, "-|/");
    }

    public static String getShortDateString(String strDate, String delimiter) {
        if (StringUtils.isBlank(strDate)) {
            return null;
        } else {
            String temp = strDate.replaceAll(delimiter, "");
            return isValidShortDateFormat(temp) ? temp : null;
        }
    }

    public static String getShortFirstDayOfMonth() {
        Calendar cal = Calendar.getInstance();
        Date dt = new Date();
        cal.setTime(dt);
        cal.set(5, 1);
        DateFormat df = getNewDateFormat("yyyyMMdd");
        return df.format(cal.getTime());
    }

    public static String getWebTodayString() {
        DateFormat df = getNewDateFormat("yyyy-MM-dd");
        return df.format(new Date());
    }

    public static String getWebString(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
        return sdf.format(date);
    }

    public static String getWebFirstDayOfMonth() {
        Calendar cal = Calendar.getInstance();
        Date dt = new Date();
        cal.setTime(dt);
        cal.set(5, 1);
        DateFormat df = getNewDateFormat("yyyy-MM-dd");
        return df.format(cal.getTime());
    }

    public static String convert(String dateString, DateFormat formatIn, DateFormat formatOut) {
        try {
            Date date = formatIn.parse(dateString);
            return formatOut.format(date);
        } catch (ParseException var4) {
            logger.warn("convert() --- orign date error: " + dateString);
            return "";
        }
    }

    public static String convertWebFormat(String dateString) {
        if (StringUtils.isEmpty(dateString)) {
            return "";
        }
        return dateString.substring(0,10);
    }

    public static String convert2WebFormat(String dateString) {
        DateFormat df1 = getNewDateFormat("yyyyMMdd");
        DateFormat df2 = getNewDateFormat("yyyy-MM-dd");
        return convert(dateString, df1, df2);
    }

    public static String convert2ChineseDtFormat(String dateString) {
        DateFormat df1 = getNewDateFormat("yyyyMMdd");
        DateFormat df2 = getNewDateFormat("yyyy年MM月dd日");
        return convert(dateString, df1, df2);
    }

    public static String convertFromWebFormat(String dateString) {
        DateFormat df1 = getNewDateFormat("yyyyMMdd");
        DateFormat df2 = getNewDateFormat("yyyy-MM-dd");
        return convert(dateString, df2, df1);
    }

    public static boolean webDateNotLessThan(String date1, String date2) {
        DateFormat df = getNewDateFormat("yyyy-MM-dd");
        return dateNotLessThan(date1, date2, df);
    }

    public static boolean dateNotLessThan(String date1, String date2, DateFormat format) {
        try {
            Date d1 = format.parse(date1);
            Date d2 = format.parse(date2);
            return !d1.before(d2);
        } catch (ParseException var5) {
            logger.debug("dateNotLessThan() --- ParseException(" + date1 + ", " + date2 + ")");
            return false;
        }
    }

    public static String getEmailDate(Date today) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss");
        String todayStr = sdf.format(today);
        return todayStr;
    }

    public static String getSmsDate(Date today) {
        SimpleDateFormat sdf = new SimpleDateFormat("MM月dd日HH:mm");
        String todayStr = sdf.format(today);
        return todayStr;
    }

    public static String formatTimeRange(Date startDate, Date endDate, String format) {
        if (endDate != null && startDate != null) {
            String rt = null;
            long range = endDate.getTime() - startDate.getTime();
            long day = range / 86400000L;
            long hour = range % 86400000L / 3600000L;
            long minute = range % 3600000L / 60000L;
            if (range < 0L) {
                day = 0L;
                hour = 0L;
                minute = 0L;
            }

            rt = format.replaceAll("dd", String.valueOf(day));
            rt = rt.replaceAll("hh", String.valueOf(hour));
            rt = rt.replaceAll("mm", String.valueOf(minute));
            return rt;
        } else {
            return null;
        }
    }

    public static String formatMonth(Date date) {
        return date == null ? null : (new SimpleDateFormat("yyyyMM")).format(date);
    }

    public static Date getBeforeDate() {
        Date date = new Date();
        return new Date(date.getTime() - 86400000L);
    }

    public static Date getDayBegin(Date date) {
        DateFormat df = new SimpleDateFormat("yyyyMMdd");
        df.setLenient(false);
        String dateString = df.format(date);

        try {
            return df.parse(dateString);
        } catch (ParseException var4) {
            return date;
        }
    }

    public static boolean dateLessThanNowAddMin(Date date, long min) {
        return addMinutes(date, min).before(new Date());
    }

    public static boolean isBeforeNow(Date date) {
        if (date == null) {
            return false;
        } else {
            return date.compareTo(new Date()) < 0;
        }
    }

    public static boolean isBeforeNow(String date) {
        if (StringUtils.isEmpty(date)) {
            return false;
        }
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(newFormat);
        LocalDateTime localTime = LocalDateTime.parse(date, dtf);
        LocalDateTime startTime = LocalDate.now().atTime(0, 0, 0);
        if(localTime.isBefore(startTime)){
            return true;
        }
        return false;
    }

    public static boolean isTomorrow(String date) {
        if (date == null) {
            return false;
        } else {
            DateFormat df = new SimpleDateFormat(webFormat);
            try {
                Date date1 = df.parse(date);
                Date date2 = df.parse(df.format(new Date()));
                return date2.compareTo(date1) > 0;
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return false;
        }
    }

    public static String getYesterday(){
        SimpleDateFormat sdf = new SimpleDateFormat(webFormat);// 2019-07-05
        Calendar c = Calendar.getInstance();
        c.add(Calendar.DATE, -1);
        return sdf.format(c.getTime());
    }

    public static String getTomorrow() {
        SimpleDateFormat sdf = new SimpleDateFormat(webFormat);// 20190705
        Calendar c = Calendar.getInstance();
        c.add(Calendar.DATE, 1);
        return sdf.format(c.getTime());
    }

    public static void main(String[] args) {
//        System.out.println(getWebString(new Date()));
        System.out.println(getTomorrow());
        System.out.println(getYesterday());
    }

    public static Date parseNoSecondFormat(String sDate) throws ParseException {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        return sDate != null && sDate.length() == "yyyy-MM-dd HH:mm".length() ? dateFormat.parse(sDate) : null;
    }

    public static String now() {
        return format(new Date(), "yyyy-MM-dd HH:mm:ss");
    }

    public static String getLocalTimeStr(LocalDateTime dateTime, String format) {
        if (Objects.isNull(dateTime)) {
            return "";
        }
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern(format);
        return dtf2.format(dateTime);
    }

    public static String getLastMonthDate(Date date, int month){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, month);
        Date dBefore = calendar.getTime();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return dateFormat.format(dBefore);
    }

    //获取两个时间之间的日期
    public static int getDatePoor(String startDate, String endDate) throws ParseException {
        DateFormat dateFormat = new SimpleDateFormat(webFormat);
        Date start = dateFormat.parse(startDate) ;
        Date end = dateFormat.parse(endDate) ;
        Calendar cal = Calendar.getInstance();
        cal.setTime(start);
        long time1 = cal.getTimeInMillis();
        cal.setTime(end);
        long time2 = cal.getTimeInMillis();
        long between_days=(time2-time1)/(1000*3600*24);
        int parseInt = Integer.parseInt(String.valueOf(between_days));
        parseInt = parseInt + 1;
        return parseInt ;
    }

    public static String compareInitialTime(String time) {
        String InitialTime = "2018-01-01 00:00:00";
        if (InitialTime.compareTo(time) > 0) {
            return CommonContext.BLANK_STRING;
        }
        return time;
    }


    public final static String FORMAT_STRING = "yyyy-MM-dd HH:mm:ss";

    public final static String[] REPLACE_STRING = new String[]{"GMT+0800", "GMT+08:00"};

    public final static String SPLIT_STRING = "(中国标准时间)";

    public final static String FORMAT_STRING2 = "EEE MMM dd yyyy HH:mm:ss z";

    /**
     * 时间解析  Sun Jan 05 2020 00:00:00 GMT 0800 (中国标准时间)
     *
     * @param dateString
     * @return
     */
    public static String timeCycle(String dateString) {
        try {
            dateString = dateString.split (Pattern.quote (SPLIT_STRING))[0].replace (REPLACE_STRING[0], REPLACE_STRING[1]);
            //转换为date
            SimpleDateFormat sf1 = new SimpleDateFormat (FORMAT_STRING2, Locale.ENGLISH);
            Date date = sf1.parse (dateString);
            return new SimpleDateFormat (FORMAT_STRING).format (date);
        } catch (Exception e) {
            throw new RuntimeException ("时间转化格式错误" + "[dateString=" + dateString + "]" + "[FORMAT_STRING=" + FORMAT_STRING + "]");
        }
    }


}
